home *** CD-ROM | disk | FTP | other *** search
/ Freelog 9 / Freelog009.iso / BAS / Internet / Rtf2Html / Source C / RTFPARSE / LIBPARSE.C next >
C/C++ Source or Header  |  1999-06-27  |  28KB  |  899 lines

  1.   
  2. /*           
  3.  * %%File: rtfreadr.c
  4.  *
  5.  * Copyright (c) 1995-1999 Bertrand LE QUELLEC
  6.  * Copyright (c) 1989-1995 Microsoft Corporation.
  7.  *
  8.  * http://perso.wanadoo.fr/blq
  9.  * blq@wanadoo.fr
  10.  */
  11.  
  12. #include <stdio.h>                                                                                           
  13.  
  14. #ifndef UNIX_SRC
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <stdlib.h>
  18. #endif
  19.  
  20. #include "html.h"
  21. #include "rtftype.h"
  22. #include "rtfdecl.h"
  23. #include "mparse.h"
  24. #include "rtfparse.h"
  25. #include "rtfchar.h"
  26. #include "rtfhtml.h"
  27.  
  28. #define SOURCE_READ 1
  29. #include "rtfreadr.h"
  30.  
  31.  
  32. static int ct = 0;              /* un compteur */
  33.  
  34.  
  35. /*
  36.  * %%Function: ecPrintChar
  37.  *
  38.  * Send a character to the output file.
  39.  */
  40. int ecPrintChar(int ch)
  41. {           
  42.     char Tab[MLEN*2];
  43.     int i = 0;
  44.     long nbimage = 0L;
  45.     static long oldimage = 0L;
  46.     static int oldCh = 0;
  47.     
  48.     
  49.     if(!flagGO || flagHeader)
  50.         return ecOK;
  51.  
  52.     /* ---------------------------------------------------
  53.      * unfortunately, we don't do a whole lot here as far
  54.      * as layout goes...
  55.      */
  56.     if (flagFootnote > 0)
  57.     {
  58.         /* Sauvegarde des notes de bas de page */
  59.         if (ch != '\n')
  60.         {
  61.             if(carnot+1 < MLEN * 2)
  62.             {
  63.                 Notes[carnot++] = (char)ch;
  64.                 Notes[carnot] = '\0';
  65.             }
  66.         }
  67.  
  68.         return ecOK;
  69.     }
  70.     else if (flagTOC)
  71.     {
  72.         lesCar[nbcar++] = (char)ch;
  73.         lesCar[nbcar] = '\0';
  74.     }
  75.     else if (flagFldrslt)
  76.     {  
  77.         Fldrslt[nbResult++] = (char)ch;
  78.         Fldrslt[nbResult] = '\0';
  79.     }
  80.     else if (flagBKMK)
  81.     {
  82.         lesBkmk[nbBk++] = (char)ch;
  83.         lesBkmk[nbBk] = '\0';
  84.     }    
  85.     else if(flagTableau)
  86.     {
  87.         /* Sauvegarde des cellules du tableau en cours */
  88.         if(carcell+1 < MLEN * 3)
  89.         {
  90.             cellule[carcell++] = (char)ch;
  91.             cellule[carcell] = '\0';
  92.         }
  93.     }
  94.     else if(flagPnText)
  95.     {
  96.         if(nbcar+1 < MLEN * 2)
  97.         {
  98.             if(ch == '\t')
  99.                 lesCar[nbcar++] = ' ';
  100.             else
  101.                 lesCar[nbcar++] = (char)ch;
  102.             
  103.             lesCar[nbcar] = '\0';
  104.         }
  105.  
  106.         return ecOK;
  107.     }   
  108.     else if (niveau)
  109.     {
  110.         /* Pour un affichage HTML du niveau */
  111.         if (ch != '\n')
  112.         {
  113.             if(carniv+1 < MLEN * 2)
  114.             {
  115.                 if(ch == '\t')
  116.                     leNiveau[carniv++] = ' ';
  117.                 else
  118.                     leNiveau[carniv++] = (char)ch;
  119.                 
  120.                 leNiveau[carniv] = '\0';
  121.             }
  122.         }
  123.  
  124.         return ecOK;
  125.     }
  126.     else 
  127.     { 
  128.         if (flagDD == 0 && tagDD == 1 && !tagLI)
  129.         {                         
  130.             tagDD = 0;
  131.             TestLibPrintString(TAG_BR, fpOut);
  132.         }
  133.             
  134.         if(!modeSpecial && (ch == '<' || ch == '>' || ch == '&'))
  135.         {
  136.             sprintf(Tab, "%c", (char)ch);
  137.             fprintf(fpOut, "%s", HexaToHTML(Tab));
  138.             
  139.             return ecOK;
  140.         }
  141.         else
  142.         {              
  143.             if (nbUrl == 0 && ch == 'h') /* 1 */
  144.             {          
  145.                 /* Possibilite d'une adresse W3 => http: */
  146.                 Url[nbUrl++] = (char)ch;
  147.                 Url[nbUrl] = '\0';
  148.                 flagStop = 0;
  149.             }                    
  150.             else if (nbUrl == 1 && oldCh == 'h' && ch == ' ')
  151.             {            
  152.                 putc('h', fpOut);
  153.                 putc(ch, fpOut);
  154.                            
  155.                 flagStop = 0;
  156.                 nbUrl = 0;
  157.                 Url[nbUrl] = '\0';
  158.             }
  159.             else if (nbUrl == 1 && oldCh == 'h' && ch == 't')  /* 2 */
  160.             {
  161.                 /* La probabilite s'accentue */
  162.                 Url[nbUrl++] = (char)ch;
  163.                 Url[nbUrl] = '\0';
  164.                 flagStop = 0;
  165.             }
  166.             else if (nbUrl == 2 && oldCh == 't' && ch == 't') /* 3 */
  167.             {
  168.                 /* La probabilite s'accentue... */
  169.                 Url[nbUrl++] = (char)ch;
  170.                 Url[nbUrl] = '\0';
  171.                 flagStop = 0;
  172.             }
  173.             else if (nbUrl == 3 && oldCh == 't' && ch == 'p') /* 4 */
  174.             {
  175.                 /* La probabilite est presque evidente... */
  176.                 Url[nbUrl++] = (char)ch;
  177.                 Url[nbUrl] = '\0';
  178.                 flagStop = 0;
  179.             }
  180.             else if (nbUrl == 4 && oldCh == 'p' && ch == ':') /* 5 */
  181.             {
  182.                 /* La probabilite est evidente */
  183.                 Url[nbUrl++] = (char)ch;
  184.                 Url[nbUrl] = '\0';
  185.                    oldCh = -10;
  186.                 flagStop = 0;
  187.                 
  188.                 return ecOK;
  189.             }   
  190.             else
  191.             {
  192.                       
  193.                 if (flagStop || (ch != '/' && ch != ':' && ch != '#' && ch != '~' && ch != '.' && ch != '-' && ch != '_' && !isalnum(ch)))
  194.                 {
  195.                     if (strlen(Url) > 4)
  196.                     {
  197.                         TestLibPrintString(GetHrefHTML2(Url, Url),fpOut);
  198.                         libPrintCharStd('\n', fpOut);
  199.                     }
  200.                             
  201.                     flagStop = 0;
  202.                     nbUrl = 0;
  203.                     oldCh = 0;
  204.                     Url[nbUrl] = '\0';
  205.                 }
  206.                         
  207.                 if (nbUrl && oldCh == -10)
  208.                 {   
  209.                     Url[nbUrl++] = (char)ch;
  210.                     Url[nbUrl] = '\0';
  211.                             
  212.                     return ecOK;
  213.                 }
  214.                 else
  215.                 {   
  216.                     if(strlen(Url))
  217.                     {
  218.                         /* Annulation adresse W3 */
  219.                         TestLibPrintString(Url, fpOut);
  220.                     }
  221.                                           
  222.                     flagStop = 0;
  223.                     nbUrl = 0;
  224.                     Url[nbUrl] = '\0';
  225.                 } 
  226.                             
  227.                 putc(ch, fpOut);
  228.             }
  229.             
  230.             oldCh = ch;
  231.         }
  232.     }
  233.    
  234.     return ecOK;
  235. }
  236.  
  237.  
  238. /*
  239.  * %%Function: ecParseChar
  240.  *
  241.  * Route the character to the appropriate destination stream.
  242.  */
  243. int ecParseChar(int ch)
  244. {
  245.     if (ris == risBin && --cbBin <= 0)
  246.         ris = risNorm;
  247.  
  248.     switch (rds)
  249.     {
  250.         case rdsSkip: /* Toss this character. */
  251.             break;
  252.  
  253.         case rdsNorm:
  254.             /* Output a character.
  255.              * Properties are valid at this point. */
  256.             return ecPrintChar(ch);
  257.  
  258.         default: /* handle other destinations.... */
  259.             break;
  260.     }
  261.  
  262.     return ecOK;
  263. }
  264.  
  265.  
  266. /*
  267.  * %%Function: ecPushRtfState
  268.  *
  269.  * Save relevant info on a linked list of SAVE structures. 
  270.  */
  271. static int ecPushRtfState(void)
  272. {                   
  273. #ifdef UNIX_SRC
  274.     pSAVE psaveNew = (pSAVE)calloc(1, sizeof(SAVE));
  275.                
  276.     if (!psaveNew)
  277.         return ecStackOverflow;
  278. #else  
  279.     HGLOBAL HGLB = GlobalAlloc(GPTR, sizeof(SAVE));
  280.     pSAVE psaveNew = (pSAVE)GlobalLock(HGLB);
  281.     
  282.     if(!HGLB)
  283.         return ecNO;
  284.     
  285.     if(!psaveNew)
  286.         return ecNO;
  287.             
  288.     psaveNew->phandle = HGLB;
  289. #endif
  290.  
  291.     psaveNew->pNext = psave;
  292.     psaveNew->chp = chp;
  293.     psaveNew->pap = pap;
  294.     psaveNew->sep = sep;
  295.     psaveNew->dop = dop;
  296.     psaveNew->rds = rds;
  297.     psaveNew->ris = ris;
  298.  
  299.     psave = psaveNew;
  300.  
  301.     ris = risNorm;
  302.     cGroup++;
  303.  
  304.     return ecOK;
  305. }
  306.  
  307.  
  308. /*
  309.  * %%Function: ecPopRtfState
  310.  *
  311.  * If we're ending a destination (i.e., the destination is changing),
  312.  * call ecEndGroupAction.
  313.  * Always restore relevant info from the top of the SAVE list.
  314.  */
  315. static int ecPopRtfState(void)
  316. {
  317.     int     ec        = 0;
  318.     pSAVE   psaveOld  = (pSAVE)0;
  319.                
  320.                
  321.     if (!psave)
  322.         return ecStackUnderflow;
  323.  
  324.     if (rds != psave->rds)
  325.     {
  326.         if ((ec = ecEndGroupAction(rds)) != ecOK)
  327.             return ec;
  328.     }
  329.     
  330.     chp = psave->chp;
  331.     pap = psave->pap;
  332.     sep = psave->sep;
  333.     dop = psave->dop;
  334.     rds = psave->rds;
  335.     ris = psave->ris;
  336.     
  337.     psaveOld = psave;
  338.     psave = psave->pNext;
  339.     
  340. #ifdef UNIX_SRC    
  341.     free(psaveOld);
  342. #else   
  343.     if(psaveOld->phandle)
  344.     {  
  345.         GlobalUnlock(psaveOld->phandle);
  346.         GlobalFree(psaveOld->phandle);
  347.     }
  348. #endif
  349.  
  350.     cGroup--;
  351.  
  352.     return ecOK;
  353. }
  354.  
  355.  
  356. /* 
  357.  * %%Function: ecParseRtfKeyword
  358.  *
  359.  * Step 2 :
  360.  * get a control word (and it's associated value) and
  361.  * call ecTranslateKeyword to dispatch the control.
  362.  */
  363. static int ecParseRtfKeyword(FILE * fp)
  364. {
  365.     int     ch      = 0;
  366.     char    fParam  = fFalse;
  367.     char    fNeg    = fFalse;
  368.     int     param   = 0;   
  369.     int     flag    = 0;
  370.     char    * pch   = (char *)0;
  371.     char    szKeyword   [30];
  372.     char    szParameter [20];
  373.                   
  374.                   
  375.     szKeyword[0]   = '\0';
  376.     szParameter[0] = '\0'; 
  377.        
  378.     if ((ch = getc(fp)) == EOF)
  379.         return ecEndOfFile;
  380.  
  381.     /* a control symbol ; no delimiter. */
  382.     if (!isalpha(ch) && ch != '\'')
  383.     {
  384.         szKeyword[0] = (char) ch;
  385.         szKeyword[1] = '\0';   
  386.             
  387.         return ecTranslateKeyword((char *)szKeyword, 0, fParam);
  388.     }
  389.  
  390.     /* Caractere special : accent */
  391.     if (ch == '\'') 
  392.     {          
  393.         /* Les caracteres accentues sont stockes sous forme hexa
  394.          * sur deux caracteres apres le code RTF \'
  395.          */           
  396.         flag = 1;
  397.         
  398.         /*  Enregistrement du caractere special quote ' */
  399.         szKeyword[0] = (char) ch;
  400.         szKeyword[1] = '\0';   
  401.         pch = (char *)szKeyword;
  402.  
  403.         if ((ch = getc(fp)) == EOF)
  404.             return ecEndOfFile;
  405.  
  406.         szKeyword[1] = (char) ch;  
  407.                      
  408.         /* Si le second code hexa est un chiffre
  409.          * on le recupere plus loin pour le passer a param
  410.          * si le code est un caractere on le stocke.
  411.          */         
  412.         if ((ch = getc(fp)) == EOF)
  413.             return ecEndOfFile;
  414.  
  415.         szKeyword[2] = '\0';
  416.  
  417.         if (!isdigit(ch))
  418.         {             
  419.             fParam = fFalse;   
  420.             param = ch; 
  421.         }
  422.     }
  423.     else
  424.     {
  425.         for (pch = (char *)szKeyword; isalpha(ch); ch = getc(fp))
  426.             *pch++ = (char) ch;
  427.     
  428.         *pch = '\0';
  429.     }
  430.  
  431.  
  432.     if (ch == '-')
  433.     {
  434.         fNeg = fTrue;
  435.     
  436.         if ((ch = getc(fp)) == EOF)
  437.             return ecEndOfFile;
  438.     }
  439.     
  440.     if (isdigit(ch))
  441.     {
  442.         /* a digit after the control means we have a parameter */
  443.         fParam = fTrue;
  444.                 
  445.         /* Dans le cas d'une detection de caracteres speciaux */
  446.         if (!flag)
  447.         {
  448.             for (pch = (char *)szParameter; isdigit(ch); ch = getc(fp))
  449.                 *pch++ = (char) ch;
  450.         }
  451.         else
  452.         {              
  453.             /* recuperation d'un seul caractere. */
  454.             pch = (char *)szParameter;
  455.             *pch++ = (char) ch;
  456.         }
  457.         
  458.         *pch  = '\0';
  459.         param = atoi(szParameter);
  460.             
  461.         if (fNeg)
  462.             param = -param;
  463.         
  464.         lParam = atol(szParameter);
  465.         
  466.         if (fNeg)
  467.             param = -param;
  468.     }
  469.  
  470.                      
  471.     /* Inutile de renvoyer le caractere special */
  472.     if (ch != ' ' && !flag)
  473.         ungetc(ch, fp);
  474.     
  475.     return ecTranslateKeyword(szKeyword, param, fParam);
  476. }
  477.  
  478.  
  479. /*
  480.  * %%Function: ecRtfParse
  481.  * 
  482.  * Step 1:
  483.  * Isolate RTF keywords and send them to ecParseRtfKeyword;
  484.  * Push and pop state at the start and end of RTF groups;
  485.  * Send text to ecParseChar for further processing.
  486.  */
  487. int ecRtfParse(FILE * fp)
  488. {
  489.     register int ch      = 0;
  490.     register int oldCh   = 0;
  491.     
  492.     int ec      = 0;
  493.     int cNibble = 2;
  494.     int b       = 0;
  495.     int nbtok   = 0;
  496.     int par     = 0;
  497.     int flagTok = 0;
  498.     int flagPict = 0;
  499.     char token[MLEN * 2];
  500.                
  501.                
  502.     while ((ch = getc(fp)) != EOF)
  503.     {
  504.         if (cGroup < 0)
  505.             return ecStackUnderflow;
  506.        
  507.         /* if we're parsing binary data, handle it directly */
  508.         if (ris == risBin)
  509.         {
  510.             if ((ec = ecParseChar(ch)) != ecOK)
  511.                 return ec;
  512.         }
  513.         else
  514.         {
  515.             switch (ch)
  516.             {
  517.                 case '{':
  518.                     if(flagFootnote > 0)
  519.                         par += 1;
  520.  
  521.                     if(crochet < 0) crochet = 0;
  522.  
  523.                     crochet += 1;
  524.  
  525.                     if ((ec = ecPushRtfState()) != ecOK)
  526.                         return ec;
  527.  
  528.                     break;
  529.                         
  530.                 case '}':
  531.                     if (flagBKMK) 
  532.                     {        
  533.                         /* Detection d'une arrivee d'ancre : insertion d'un point d'arrivee */
  534.                         if (strlen(lesBkmk))
  535.                         {
  536.                             if (strlen(lesBkmk) >= 4)
  537.                             {
  538.                                 if (strncmp(lesBkmk, "_Toc", 4))
  539.                                     TestLibPrintString(GetANameHTML2(lesBkmk), fpOut);
  540.                             }
  541.                             else
  542.                                 TestLibPrintString(GetANameHTML2(lesBkmk), fpOut);
  543.                         }
  544.                         
  545.                         flagBKMK = 0;
  546.                         nbBk = 0;
  547.                         lesBkmk[nbBk] = '\0';
  548.                     }
  549.                     else if (flagFldrslt) 
  550.                     {                  
  551.                         /* Detection d'un renvoie : insertion d'une ancre interne point de dΘpart */
  552.                         if (strlen(Fldrslt))
  553.                         {   
  554.                             if (strlen(lesBkmk))                                  
  555.                             {
  556.                                 TestLibPrintString(GetAHNameHTML2(lesBkmk, Fldrslt), fpOut);
  557.                             }
  558.                             else
  559.                                 TestLibPrintString(Fldrslt, fpOut);
  560.                         }
  561.  
  562.                         nbResult = nbBk = 0;
  563.                         Fldrslt[nbResult] = lesBkmk[nbBk] = '\0';
  564.                     }  
  565. ;                   
  566.                     flagFldrslt = 0;
  567.                     
  568.                     if(flagFootnote > 0)
  569.                         par -= 1;
  570.  
  571.                     if(par < 0)
  572.                     {
  573.                         par = 0;
  574.                         flagFootnote = -1;
  575.                     }
  576.                     
  577.                     /* Affichage de fin de style eventuel */
  578.                     ecPrintItalicF    (fpOut);
  579.                     ecPrintBoldF    (fpOut);
  580.                     
  581.                     if ((ec = ecPopRtfState()) != ecOK)
  582.                         return ec;
  583.  
  584.                     if(valCrochetH == crochet)
  585.                         flagHeader = 0;
  586.  
  587.                     if(valCrochetF == crochet)
  588.                         valCrochetF = 0;
  589.                         
  590.                     flagREF = 0;
  591.                     crochet -= 1;  
  592.                     break;
  593.                         
  594.                 case '\\':  
  595.                     if ((ec = ecParseRtfKeyword(fp)) != ecOK)
  596.                         return ec;
  597.  
  598.                     break;
  599.                         
  600.                 case 0x0d:
  601.                 case 0x0a:/* cr and lf are noise characters... */
  602.                     break;
  603.                 
  604.                 default:
  605.                     if(crochet)
  606.                     {
  607.                         if(ch == ' ')
  608.                         {
  609.                             token[nbtok] = '\0';
  610.  
  611.                             if(!strcmp(token, "SYMBOL") || !strcmp(token, "symbol"))
  612.                             {    
  613.                                 flagTok = 1;
  614.                             }
  615.                             else if(!strcmp(token, "TOC"))
  616.                             {
  617.                                 flagTok = 0;
  618.                                 flagTOC = 1;
  619.  
  620.                                 ecPrintItalicF    (fpOut);
  621.                             } 
  622.                             else if(!strcmp(lesBkmk, "REF"))
  623.                             {   
  624.                                 flagREF = 1;
  625.                                 nbBk = 0;
  626.                                 lesBkmk[nbBk] = '\0';
  627.                             }
  628.                             else if(!strcmp(token, "INCLUDEPICTURE"))
  629.                             {
  630.                                 flagPict = 1;
  631.                             }
  632.                             else                                 
  633.                             {
  634.                                 if (flagREF && nbBk)
  635.                                 {                               
  636.                                     flagREF = 0;
  637.                                     nbBk = 0;
  638.                                 }
  639.                                 else if (flagPict)
  640.                                 {              
  641.                                     if (strlen(token) > 0)
  642.                                     {
  643.                                         ++nbFigure;
  644.                                         flagPict = 0;
  645.                                         TestLibPrintString(GetImgSrcHTML(token), fpOut);
  646.                                     }
  647.                                 }    
  648.                                 else if(flagTok)
  649.                                 {
  650.                                     flagTok = 0;
  651.  
  652.                                     switch(atoi(token))
  653.                                     {
  654.                                         case 35:
  655.                                             TestLibPrintString(TokenToHTML("numbersign"), fpOut);
  656.                                             break;
  657.                                         
  658.                                         case 37:
  659.                                             TestLibPrintString(TokenToHTML("percent"), fpOut);
  660.                                             break;
  661.                                         
  662.                                         case 38:
  663.                                             TestLibPrintString(TokenToHTML("ampersand"), fpOut);
  664.                                             break;
  665.                                         
  666.                                         case 95:
  667.                                             TestLibPrintString(TokenToHTML("underscore"), fpOut);
  668.                                             break;
  669.                                         
  670.                                         case 97:
  671.                                             TestLibPrintString(TokenToHTML("alpha"), fpOut);
  672.                                             break;
  673.                                         
  674.                                         case 98:
  675.                                             TestLibPrintString(TokenToHTML("beta"), fpOut);
  676.                                             break;
  677.                                         
  678.                                         case 171:
  679.                                             TestLibPrintString(TokenToHTML("arrowboth"), fpOut);
  680.                                             break;
  681.                                         
  682.                                         case 172:
  683.                                             TestLibPrintString(TokenToHTML("arrowleft"), fpOut);
  684.                                             break;
  685.                                         
  686.                                         case 174:
  687.                                             TestLibPrintString(TokenToHTML("arrowright"), fpOut);
  688.                                             break;
  689.                                         
  690.                                         case 176:
  691.                                             TestLibPrintString(TokenToHTML("degree"), fpOut);
  692.                                             break;
  693.                                         
  694.                                         case 177:
  695.                                             TestLibPrintString(TokenToHTML("plusminus"), fpOut);
  696.                                             break;
  697.                                         
  698.                                         case 179:
  699.                                             TestLibPrintString(TokenToHTML("greaterequal"), fpOut);
  700.                                             break;
  701.                                         
  702.                                         case 183:
  703.                                             if(!flagTableau)
  704.                                             {
  705.                                                 if (!tagLI)
  706.                                                 {
  707.                                                     tagLI = 1;
  708.     
  709.                                                     libPrintCharStd('\n', fpOut);
  710.                                                     libPrintString(TAG_BQUOTE, fpOut);
  711.                                                     libPrintString(TAG_LI, fpOut);
  712.                                                 }
  713.                                                 else
  714.                                                 {
  715.                                                     libPrintCharStd('\n', fpOut);
  716.                                                     libPrintString(TAG_LI, fpOut);
  717.                                                 }
  718.                                             }
  719.  
  720.                                             break;
  721.                                         
  722.                                         case 184:
  723.                                             TestLibPrintString(TokenToHTML("mathdivise"), fpOut);
  724.                                             break;
  725.                                         
  726.                                         case 185:
  727.                                             TestLibPrintString(TokenToHTML("notequal"), fpOut);
  728.                                             break;
  729.                                         
  730.                                         case 187:
  731.                                             TestLibPrintString(TokenToHTML("tilde"), fpOut);
  732.                                             break;
  733.                                         
  734.                                         case 188:
  735.                                             TestLibPrintString(TokenToHTML("ellipsis"), fpOut);
  736.                                             break;
  737.                                         
  738.                                         case 210:
  739.                                             TestLibPrintString(TokenToHTML("registred"), fpOut);
  740.                                             break;
  741.  
  742.                                         case 211:
  743.                                             TestLibPrintString(TokenToHTML("copyright"), fpOut);
  744.                                             break;
  745.                                         
  746.                                         case 212:
  747.                                         case 228:
  748.                                             TestLibPrintString(TokenToHTML("trademark"), fpOut);
  749.                                             break;
  750.                                         
  751.                                         case 219:
  752.                                             TestLibPrintString(TokenToHTML("arrowdblboth"), fpOut);
  753.                                             break;
  754.                                         
  755.                                         case 220:
  756.                                             TestLibPrintString(TokenToHTML("arrowdblleft"), fpOut);
  757.                                             break;
  758.                                         
  759.                                         case 222:
  760.                                             TestLibPrintString(TokenToHTML("arrowdblright"), fpOut);
  761.                                             break;
  762.                                     }
  763.                                 }
  764.                             }
  765.                                                         
  766.                             nbtok = 0;
  767.                             token[nbtok] = '\0';
  768.                         }
  769.                         else
  770.                         {
  771.                             if(nbtok+1 < MLEN*2 && (nbtok || flagTok || flagPict))
  772.                                 token[nbtok++] = ch;
  773.                                                 
  774.                             if (nbBk+1 < MLEN && (nbBk || flagREF) && !flagBKMK)
  775.                             {
  776.                                 lesBkmk[nbBk++] = (char)ch;
  777.                                 lesBkmk[nbBk] = '\0';
  778.                             }
  779.                                                         
  780.                             /* Symbol - symbol - TOK - REF - INCLUDE */
  781.                             if(ch == 's' || ch == 'S' || ch == 'T' || ch == 'I')
  782.                             {
  783.                                 nbtok = 0;
  784.                                 token[nbtok++] = ch;
  785.                             }
  786.                             else if (ch == 'R' && oldCh == ' ')
  787.                             {        
  788.                                 nbBk = 0;
  789.                                 lesBkmk[nbBk++] = (char)ch;
  790.                                 lesBkmk[nbBk] = '\0';
  791.                             }
  792.                         }
  793.                     }
  794.  
  795.                     if (ris == risNorm)
  796.                     {
  797.                         if ((ec = ecParseChar(ch)) != ecOK)
  798.                             return ec;
  799.                     }
  800.                     else
  801.                     {
  802.                         /* parsing hex data */
  803.                         if (ris != risHex)
  804.                             return ecAssertion;
  805.                         
  806.                         b = b << 4;
  807.                         
  808.                         if (isdigit(ch))
  809.                             b += (char) ch - '0';
  810.                         else
  811.                         {
  812.                             if (islower(ch))
  813.                             {
  814.                                 if (ch < 'a' || ch > 'f')
  815.                                     return ecInvalidHex;
  816.  
  817.                                 b += (char) ch - 'a';
  818.                             }
  819.                             else
  820.                             {
  821.                                 if (ch < 'A' || ch > 'F')
  822.                                     return ecInvalidHex;
  823.  
  824.                                 b += (char) ch - 'A';
  825.                             }
  826.                         }
  827.                     
  828.                         cNibble--;
  829.  
  830.                         if (!cNibble)
  831.                         {
  832.                             if ((ec = ecParseChar(ch)) != ecOK)
  833.                                 return ec;
  834.  
  835.                             cNibble = 2;
  836.                             b = 0;
  837.                             ris = risNorm;
  838.                         }
  839.                     } /* end else (ris != risNorm) */
  840.                 
  841.                     break;
  842.             } /* switch */
  843.         } /* else (ris != risBin) */
  844.         
  845.         oldCh = ch;
  846.  
  847.     } /* while */
  848.  
  849.     ecDetectPard();
  850.     ecFootnote();
  851.     
  852.     if (cGroup < 0)
  853.         return ecStackUnderflow;
  854.     
  855.     if (cGroup > 0)
  856.         return ecUnmatchedBrace;
  857.         
  858.     if (flagFRAME)
  859.     {                                      
  860.         libPrintCharStd('\n', fpTable);
  861.         
  862.         for (ec = 0; ec <= oldNiveau; ec++)
  863.             libPrintString(TAGf_UL, fpTable);
  864.     }
  865.  
  866.     return ecOK;
  867. }
  868.  
  869. /* 
  870.  * %%Function: TestLibPrintString
  871.  *
  872.  * 
  873.  */
  874. void TestLibPrintString(char * chaine, FILE * sortie)
  875. {     
  876.     int ct = 0;
  877.     char tmp [MLEN * 2];
  878.     
  879.     
  880.     if (flagTableau)
  881.     {
  882.         sprintf(tmp, "%s", chaine);
  883.                                         
  884.         for (ct = 0; ct < (int)strlen(tmp); ct++)
  885.         {
  886.             /* Sauvegarde des infos dans la cellule courante du tableau */
  887.             if(carcell+1 < MLEN * 4)
  888.             {
  889.                 cellule[carcell++] = tmp[ct];
  890.                 cellule[carcell] = '\0';
  891.             }
  892.             else
  893.                 break;
  894.         }
  895.     }
  896.     else
  897.         libPrintString(chaine, sortie);
  898. }
  899.